//
// Created by 33145 on 2023/2/6.
//

#include "http_session.h"
#include "http_parser.h"

namespace sylar {
  namespace http {

    HttpSession::HttpSession(Socket::ptr sock, bool owner)
            :SocketStream(sock, owner) {
    }

    HttpRequest::ptr HttpSession::recvRequest() {
      HttpRequestParser::ptr parser(new HttpRequestParser);
      uint64_t buff_size = HttpRequestParser::GetHttpRequestBufferSize();
      // uint64_t buff_size = 100;
      std::shared_ptr<char> buffer(
              new char[buff_size], [](char* ptr){
                delete[] ptr;
              });
      char* data = buffer.get();
      // memset(data, 0, buff_size);
      int offset = 0;
      do {
        int len = read(data + offset, buff_size - offset);
        // 如果读取失败或对端关闭连接
        if(len <= 0) {
          close();
          return nullptr;
        }
        len += offset;
        /// execute会把解析过的部分都替换掉，现在data起步是没解析的部分（可能是消息体？）
        size_t nparse = parser->execute(data, len);
        if(parser->hasError()) {
          close();
          return nullptr;
        }
        /// offset: 剩下的没解析的内容
        offset = len - nparse;
        /// 如果缓冲区满了还没解析完？
        if(offset == (int)buff_size) {
          close();
          return nullptr;
        }
        // std::cout << "hello " <<  data << std::endl;
        if(parser->isFinished()) {
          break;
        }

      } while(true);
      /// 看起来execute只会解析请求行
      int64_t length = parser->getContentLength();
      if(length > 0) {
        std::string body;
        body.resize(length);

        int len = 0;
        if(length >= offset) {
          memcpy(&body[0], data, offset);
          len = offset;
        } else {
          memcpy(&body[0], data, length);
          len = length;
        }
        length -= offset;
        /// 如果缓冲区消息不够还得继续读
        if(length > 0) {
          if(readFixSize(&body[len], length) <= 0) {
            close();
            return nullptr;
          }
        }
        parser->getData()->setBody(body);
      }
      // 解析完之后看看他是不是 keep-alive
      parser->getData()->init();
      return parser->getData();
    }

    int HttpSession::sendResponse(HttpResponse::ptr rsp) {
      std::stringstream ss;
      ss << *rsp;
      std::string data = ss.str();
      return writeFixSize(data.c_str(), data.size());
    }

  }
}
